<?php

namespace App\Services\Draw\DrawObject;


use App\Enums\AppJumpEnum;
use App\Exceptions\BasicException;
use App\Jobs\QiPao\Draw\SeniorDrawStatisticsJob;
use App\Models\MainDB\Gift;
use App\Models\MainDB\GiftBackpack;
use App\Repositories\GiftRepository;
use App\Repositories\Senior\SeniorPropsRepository;
use App\Services\Draw\DrawConst\CacheKey;
use App\Services\Draw\Enum\DrawEnum;
use App\Services\Draw\PoolGroupObject\SeniorIndependentPoolGroup;
use App\Services\Draw\PoolGroupObject\SeniorPublicPoolGroup;
use App\Services\Tools\PushChatService;
use App\Services\Tools\PushService;
use App\Services\Tools\RedisService;
use Carbon\Carbon;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use App\Enums\RedisKeyEnum;

/**
 * 至尊夺宝抽奖实体
 * @author wrh
 */
class Senior extends Draw
{
    protected $isDrawCriticalGift = false;
    protected $cachePrefix = 'senior:';
    protected $privateKey = 'senior';
    protected $balanceNotEnoughMsg = '海星数量不足';
    protected $drawLockKey = "draw:senior:lock_";
    protected $isDrawAccumulate = false; //是否做抽奖计数累计逻辑

    public function __construct()
    {
        parent::__construct();
        $this->redisObject               = app('redis')->connection('game');
        $this->poolConfigModel           = app('model_senior_pool_config');
        $this->poolUserModel             = app('model_senior_pool_user');
        $this->poolModel                 = app('model_senior_pool');
        $this->poolPrizeModel            = app('model_senior_pool_prize');
        $this->poolGroupModel            = app('model_senior_pool_group');
        $this->giftTemplateModel         = app('model_senior_gift_template');
        $this->poolTemplateModel         = app('model_senior_pool_template');
        $this->poolDrawModel             = app('model_senior_pool_draw');
        $this->poolDrawRecordModel       = app('model_senior_pool_draw_record');
        $this->levelModel                = app('model_senior_level');
        $this->poolIndependentModel      = app('model_senior_pool_independent');
        $this->poolIndependentPrizeModel = app('model_senior_pool_independent_prize');
        $this->appointGiftModel = app('model_senior_appoint_gift');
        $this->fragmentGroupModel        = new \App\Models\GameDB\Senior\FragmentGroup();
        $this->fragmentUserRecordModel   = new \App\Models\GameDB\Senior\FragmentUserRecord();
        $this->fragmentPoolRecordModel   = new \App\Models\GameDB\Senior\FragmentPoolRecord();
        $this->fragmentPoolModel         = new \App\Models\GameDB\Senior\FragmentPool();

        $this->checkRecordModel = app('model_senior_draw_check_record');
        $this->addPoolAccountRecordModel = app('model_senior_draw_add_pool_account_record');
        $this->addPoolRepo = app('repo_add_pool_senior');

        $this->independentPoolGroup = new SeniorIndependentPoolGroup($this->redisObject);
        $this->publicPoolGroup      = new SeniorPublicPoolGroup($this->redisObject);
    }

    public function getUserDrawInfo($userId)
    {
        //获取用户信息
        $userInfo   = $this->poolUserModel->firstOrCreate($userId);
        $luckyValue = $this->redisObject->get($this->cachePrefix . "seasonValue");

        $poolConfig                 = $this->poolConfigModel->one(['id' => 1]);
        $userInfo['lucky_value']    = $luckyValue > $poolConfig->lucky_count ? ($luckyValue - $poolConfig->lucky_count) : $luckyValue;
        $userInfo['lucky_count']    = $poolConfig->lucky_count;
        $userInfo['help_info']      = $poolConfig->help_info;
        $userInfo[$this->privateKey.'_balance_coin'] = $poolConfig->balance_coin;
        $userInfo['draw_list']  = explode(',',app('model_config')->getValue('FRAG_DRAW_INFO') ?? '1,10,100');
        $userInfo['coin']       = app('model_user')->where('user_id', $userId)->value('money');
        if (!empty($poolConfig->balance_gift_id)) {
            $balance_gift = $poolConfig->mall_products->only(['name', 'picture']);
            $balance_gift['name'] = '购买一天'.$balance_gift['name'];
            $userInfo['balance_gift'] = $balance_gift;
        }
        $userInfo['is_show_plutocrat'] = $this->getAllPlutocratList() ? 1 : 0;
        $userInfo['fragment_nums']     = $this->redisObject->get($this->privateKey.':fragment_pool:nums') ?? '0';
        return $userInfo;
    }

    public function isNovice($user, $poolConfig)
    {
        return $user->input_week <= $poolConfig->novice_coin;
    }

    public function getExpLevel(int $exp)
    {
        return 0;
    }

    // 添加抽奖记录
    public function addDrawRecord($user, $poolGroup, array $drawIOPut, Collection $gifts, $criticalGift, array $drawPrizes, int $drawCount, int $drawPrizesCount)
    {
        //并发处理
        if ($poolGroup->group_id == 0) {
            $poolGroup->group_id = key($drawPrizes);
        }


        $drawData = [
            "user_id"    => $user->user_id,
            "group_id"   => $poolGroup->group_id,
            "tag"        => $poolGroup->tag,
            "count"      => $drawCount,
            "gift_count" => $drawPrizesCount,
            "input"      => $drawIOPut['input'],
            "output"     => $drawIOPut['output'],
        ];

        $poolDrawId = $this->poolDrawModel->createDataGetId($drawData);
        if (empty($poolDrawId)) {
            throw new BasicException(-1, '抽奖记录保存错误');
        }
        $drawPrizesRecord = [];
        foreach ($drawPrizes as $groupId => $groupPrize) {
            foreach ($groupPrize as $prizeId => $prizeCount) {
                $gift               = $gifts->where('gift_template_id', $prizeId)->first();
                $drawPrizesRecord[] = ['user_id' => $user->user_id, 'draw_id' => $poolDrawId, 'group_id' => $groupId,
                                       'gift_id' => $gift->id, 'gift_price' => $gift->price, 'count' => $prizeCount, 'gift_type' => $gift->type];
            }
        }
        if (!empty($criticalGift)) {
            $drawPrizesRecord[] = ['user_id' => $user->user_id, 'draw_id' => $poolDrawId, 'group_id' => 0,
                                   'gift_id' => $criticalGift['id'], 'gift_price' => 0, 'count' => $criticalGift['count'], 'gift_type' => DrawEnum::PROP_GIFT_TYPE];


        }

        $this->poolDrawRecordModel->insert($drawPrizesRecord);
        return $drawData;
    }

    public function getDrawJob($poolGroup, $user, $jobData)
    {
        return new SeniorDrawStatisticsJob($poolGroup, $user, $jobData, $this->cachePrefix);

    }

    public function getGiftList(array $drawPrizes)
    {
        //根据模板礼物ID获取礼物ID
        $templateGiftIds = [];
        $giftPrizes      = [];
        foreach ($drawPrizes as $groupId => $groupPrize) {
            foreach ($groupPrize as $prizeId => $prizeCount) {
                $templateGiftIds[] = $prizeId;
                if (isset($giftPrizes[$prizeId])) {
                    $giftPrizes[$prizeId] += $prizeCount;
                } else {
                    $giftPrizes[$prizeId] = $prizeCount;
                }
            }
        }

        $templateGiftList   = $this->giftTemplateModel->getGiftListByIds($templateGiftIds, ['id', 'type', 'gift_id']);
        $templateGiftWithId = $templateGiftList->where('type', DrawEnum::NORMAL_GIFT_TYPE)->KeyBy('gift_id');
        //$templatePropWithId = $templateGiftList->where('type', DrawEnum::PROP_GIFT_TYPE)->KeyBy('gift_id');
        $giftInfoList = (new GiftRepository())->giftsByIds($templateGiftWithId->keys()); // 抽中礼物信息

        foreach ($giftInfoList as $giftInfo) {
            $giftInfo->gift_template_id = $templateGiftWithId[$giftInfo['id']] ? $templateGiftWithId[$giftInfo['id']]['id'] : 0;
            $giftInfo->count            = $giftPrizes[$giftInfo->gift_template_id] ?? 0;
            $giftInfo->type             = DrawEnum::NORMAL_GIFT_TYPE;
        }

//        if (!empty($templatePropWithId)) {
//            //查询道具价格
//            $propGiftList = app('model_props')->select('id', 'name', 'prope_icon as picture', 'price')->whereIn('id', $templatePropWithId->keys())->where('is_delete', 0)->get();
//            if ($propGiftList->isNotEmpty()) {
//                $propGiftListWithId = $propGiftList->KeyBy('id');
//                foreach ($templatePropWithId as $templateId => $propGift) {
//                    $propGiftInfo                   = $propGiftListWithId[$propGift['gift_id']];
//                    $propGiftInfo->gift_template_id = $propGift->id;
//                    $propGiftInfo->count            = $giftPrizes[$propGift->id] ?? 0;
//                    $propGiftInfo->type             = DrawEnum::PROP_GIFT_TYPE;
//                    $giftInfoList[]                 = $propGiftInfo;
//                }
//            }
//        }

        return $giftInfoList;
    }

    public function getNotifyGiftList($count)
    {
        $cacheNotifyRecordList = $this->redisObject->get($this->cachePrefix . "notifyRecordList:" . $count);
        if (!empty($cacheNotifyRecordList)) {
            $notifyRecordList = json_decode($cacheNotifyRecordList, true);
        }
        if (empty($notifyRecordList)) {
            $notifyRecordList = parent::getNotifyGiftList($count);
            $this->redisObject->setex($this->cachePrefix . "notifyRecordList:" . $count, 60, json_encode($notifyRecordList));
        }

        return $notifyRecordList;
    }

//    public function push($user, array $notifyPushData, array $broadcastPushData, array $extraPushData)
//    {
//        try {
//            $userChatLabel = RedisService::getUserChatLabel($user->user_id);
//            //$levelInfo = $this->levelModel->one(['level' => $user->level]);
//
//            foreach ($notifyPushData as $value) {
//                // (new PushChatService())->lotterySeniorNew($userChatLabel, $value);
//            }
//
//
//            foreach ($notifyPushData as $value) {
//                (new PushChatService())->lotterySeniorNew($userChatLabel, $value);
//            }
//
//            (new PushService())->lotterySenior($broadcastPushData, $userChatLabel);
//        } catch (\Exception $e) {
//            return false;
//        }
//        return true;
//    }

    public function push($user, array $notifyPushData, array $broadcastPushData, array $extraPushData)
    {
        try {
            $userChatLabel = RedisService::getUserChatLabel($user->user_id);
            $uni_key = uniqidReal();
            $getMillisecond = getMillisecond();
            $PushService = new PushService();
            // /幸运票品
            $notifyPush = [];
            if(!empty($notifyPushData)){
                $ext_data = $userChatLabel;
                $txt = "<font color='#22C4F1'>在星动游乐场-豪华转盘中获得了</font>";
                foreach ($notifyPushData as $key => $value) {
                    $txt .= '<font color="#FFC07D">价值' . $value->price . '</font>';
                    $txt .= '<font color="#C5A1FF">金币的</font>';
                    //$txt .= "<font color='#22C4F1'> </font>";
                    $txt .= '<font color="#72D1E0">' . $value->name . ' x ' . $value->count .'.'.'</font>';
                }

                $ext_data['type'] = PushService::GAME_PUSH_STATUS;
                $ext_data['action'] = 1;
                $ext_data['show_area'] = [
                    PushChatService::AREA_LUCKY,
                    PushChatService::AREA_ALL,
                ];
                $ext_data['show_label_id'] = [
                    PushChatService::AREA_LUCKY,
                ];
                $ext_data['bg_type'] = $this->privateKey;
                $notifyPush = [
                    'content' => $txt,
                    'uni_key' => $uni_key,
                    'extra' => $ext_data
                ];
            }
            $broadcastPush = [];
            if(!empty($broadcastPushData)){
                $txt = "<font color='#FFEB66'>" . mb_substr($userChatLabel['nickname'], 0, 1) . "**</font><font color='#FFFFFF'> 获得了价值 </font>";
                $txt_extra = [];
                foreach ($broadcastPushData as $gift) {
                    $txt_extra [] = [
                        'text' => $txt . "<font color='#FFEB66'>" . $gift->price . "金币的</font>" . "<font color='#73E8FF'>" . $gift->name . "</font><font color='#FFFFFF'>X" . $gift->count . "</font>",
                        'picture' => $gift->picture,
                    ];
                }
                $broadcastPush = [
                    'uni_key' => $uni_key,
                    'time' => $getMillisecond,
                    'msg'  => $txt_extra,
                    'special' => RedisService::getBroadcastSpecial($user->user_id),
                    'bg_type' => $this->privateKey,
                    'show_grade' => $this->showBroadcastGrade(),
                ];
            }

            $PushService->publicGamePush($notifyPush,$broadcastPush,[],[],$uni_key,$getMillisecond);

        } catch (\Exception $e) {
            return false;
        }
        return true;
    }

    public function getUserQueuePool($userId, int $count)
    {
        return null;

    }

//    public function getUserPool()
//    {
//
//    }

//
//    /**
//     * @param int $userId
//     * @param int $count
//     */
//    public function swap(int $userId, int $count)
//    {
//
//    }

    public function dealFragment($user, int $drawCount, array $poolConfig, array $gifts, array $extra = [])
    {
        /*$this->redisObject->set($this->cachePrefix.'user', json_encode($user, JSON_UNESCAPED_UNICODE));
        $this->redisObject->set($this->cachePrefix.'poolConfig', json_encode($poolConfig, JSON_UNESCAPED_UNICODE));
        $this->redisObject->set($this->cachePrefix.'gifts', json_encode($gifts, JSON_UNESCAPED_UNICODE));*/

        $fragment_group = RedisService::getDrawFragmentGroup($this->cachePrefix, $this->fragmentGroupModel, $this->giftTemplateModel);
        if (empty($fragment_group)) {
            throw new BasicException(-1, '---碎片组合配置异常---');
        }
        $fragmentPoolModel  = $this->fragmentPoolModel;
        $fragmentPoolInfo   = $fragmentPoolModel::query()->lockForUpdate()->find(1);
        if (empty($fragmentPoolInfo) || empty($poolConfig['send_gift_id'])) {
            throw new BasicException(-1, '--碎片配置异常--');
        }
        $fragment_exchange_ratio    = $poolConfig['fragment_exchange_ratio'];//碎片产生的比例
        $fragment_max_share         = $poolConfig['fragment_max_share'];//碎片最大分成数量

        #计算碎片池数量
        $fragment_pool_num_key = CacheKey::getFragmentPoolNumsKey($this->privateKey);
        $now_add_num       = floor($fragment_exchange_ratio * $drawCount * $poolConfig['balance_coin'] / 100);
        $now_num           = $this->redisObject->get($fragment_pool_num_key);
        $pool_num = $this->redisObject->incrby($fragment_pool_num_key, $now_add_num);

        //每日新增数量、强制触发后清0
        $redis_key = CacheKey::getFragmentForceTriggerKey($this->privateKey);
        $this->redisObject->hincrby($redis_key, 'fragment_daily_add_num', $now_add_num);

        $poolRecordData[]   = [
            'relation_id'   => 0,
            'change_num'    => $now_add_num,
            'num_before'    => $now_num,
            'num_after'     => $pool_num
        ];
        $send_gift = [];
        $user_change_num = 0;
        $that_gift_template_ids = array_column($gifts, 'gift_template_id');
        $that_gift_count = count($that_gift_template_ids);

        foreach ($fragment_group as $group) {
            //用户是否完成该组全部条件 给用户发奖励
            $group_count = count($group['gift_template_ids']);
            if ($group['draw_count'] == $drawCount && $group['gift_template_ids'] === array_intersect($group['gift_template_ids'], $that_gift_template_ids)
                && $group_count + $group['other_num'] <= $that_gift_count ) {
                $now_num = $this->redisObject->get($fragment_pool_num_key);
                $now_fragment_num   = floor($now_num * $group['rate'] / 100);
                $now_fragment_num   = ($now_fragment_num > $fragment_max_share ? $fragment_max_share : $now_fragment_num);

                if($now_fragment_num > 0) {
                    $pool_num = $this->redisObject->decrby($fragment_pool_num_key, $now_fragment_num);
                    $o_str = '';
                    if ($extra['is_force_trigger']) {
                        $o_str .= '强制触发';
                    }
                    $userRecordData = [
                        'user_id'           => $user['user_id'],
                        'change_num'        => $now_fragment_num,
                        'fragment_group_id' => $group['id'],
                        'send_gift_id'      => $poolConfig['send_gift_id'],
                        'is_force_trigger'  => $extra['is_force_trigger'] ? 1 : 0,
                        'desc'              => "仅记录：获得{$now_fragment_num}".$o_str,
                    ];
                    $userRecordInsertId = $this->fragmentUserRecordModel->insertGetId($userRecordData);
                    if (!$userRecordInsertId) {
                        throw new BasicException(-1, '抽奖---碎片错误');
                    }
                    app('model_gift_backpack')->addGift((int)$user['user_id'], (int)$poolConfig['send_gift_id'], (int)$now_fragment_num);

                    $poolRecordData[]   = [
                        'relation_id'   => $userRecordInsertId,
                        'change_num'    => -$now_fragment_num,
                        'num_before'    => $now_num,
                        'num_after'     => $pool_num,
                    ];
                    $user_change_num += $now_fragment_num;//用户在这次中获取的碎片总数
                    $send_gift = array_merge($poolConfig['send_gift'], ['count' => $user_change_num]);
                }
            }
        }

        $fragmentPoolInfo->nums = $pool_num;
        $poolUpdateRes       = $fragmentPoolInfo->save();
        $poolRecordInsertRes = $this->fragmentPoolRecordModel::query()->insert($poolRecordData);

        if (!$poolUpdateRes && !$poolRecordInsertRes) {
            throw new BasicException(-1, '抽奖--碎片错误');
        }
        $user_fragment_data = [];
        if ($user_change_num) {
            $roomId = RedisService::getUserInRoom($user['user_id']);
            $roomName = RedisService::getRoomDetailByRoomId($roomId, 'room_name');
            $nickName = RedisService::getUserBaseInfo($user['user_id'], 'nickname', true);
            $user_fragment_data = [
                'user_id' => $user['user_id'],
                'room_name' => $roomName ?? '',
                'nickname' => $nickName,
                'user_change_num' => $user_change_num,
            ];
            $pushData = [
                'data' => $user_fragment_data,
                'bg_type' => $this->privateKey,
                'show_grade' => $this->showBroadcastGrade(),
            ];
            (new PushService(0, $roomId))->fragmentPush($pushData);
        }

        return [
            'send_gift' => $send_gift,
            'user_fragment_data' => $user_fragment_data ?: null,
        ];
    }

}
